#pragma once
#include <Rz/Object.h>
#include <Rz/IEquatable.h>

namespace Rz { namespace Graphics { namespace Render {

enum class VertexElementFormat
{
	Single,
	Vector2,
	Vector3,
	Vector4,
	Color,
	Byte4,
	Short2,
	Short4,
	NormalizedShort2,
	NormalizedShort4,
	HalfVector2,
	HalfVector4
};

enum class VertexElementUsage
{
	Position,
	Color,
	TextureCoordinate,
	Normal,
	Binormal,
	Tangent,
	BlendIndices,
	BlendWeight,
	Depth,
	Fog,
	PointSize,
	Sample,
	TessellateFactor
};

class VertexElement :
	public Object,
	public IEquatable<VertexElement>
{
	public:
		RZ_RTTI(Rz::Graphics::Render, VertexElement);
		RZ_RTTI_IMPLEMENTS(Object, IEquatable<VertexElement>);
		RZ_RTTI_END;

		VertexElement()
			: VertexElement(0, VertexElementFormat::Color, VertexElementUsage::Color, 0)
		{

		}

		VertexElement(u32 offset, VertexElementFormat elementFormat, VertexElementUsage elementUsage, u32 usageIndex)
			: _offset(offset)
			, _vertexElementFormat(elementFormat)
			, _vertexElementUsage(elementUsage)
			, _usageIndex(usageIndex)
		{

		}

		RZ_INLINE virtual u32 GetOffset() const { return _offset; }
		RZ_INLINE virtual void SetOffset(u32 offset) { _offset = offset; }

		RZ_INLINE virtual VertexElementFormat GetVertexElementFormat() const { return _vertexElementFormat; }
		RZ_INLINE virtual void SetOffset(VertexElementFormat format) { _vertexElementFormat = format; }

		RZ_INLINE virtual VertexElementUsage GetVertexElementUsage() const { return _vertexElementUsage; }
		RZ_INLINE virtual void SetVertexElementUsage(VertexElementUsage usage) { _vertexElementUsage = usage; }

		RZ_INLINE virtual u32 GetUsageIndex() const { return _usageIndex; }
		RZ_INLINE virtual void SetUsageIndex(u32 usageIndex) { _usageIndex = usageIndex; }

		// IEquatable
		RZ_INLINE bool Equals(const VertexElement& r) const
		{
			return (
				_offset == r._offset &&
				_vertexElementFormat == r._vertexElementFormat &&
				_vertexElementUsage == r._vertexElementUsage &&
				_usageIndex == r._usageIndex
				);
		}

		RZ_INLINE bool operator == (const VertexElement& r) const
		{
			return Equals(r);
		}

		RZ_INLINE bool operator != (const VertexElement& r) const
		{
			return !Equals(r);
		}

	private:
		u32 _offset;
		VertexElementFormat _vertexElementFormat;
		VertexElementUsage _vertexElementUsage;
		u32 _usageIndex;
};

} } }
